package com.bkhc.order.repository;

import com.bkhc.order.entity.Order;
import com.bkhc.order.vo.OrderQuery;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

@Repository
public interface OrderRepository extends JpaRepository<Order,String> , JpaSpecificationExecutor<Order> {

    default Page<Order> findAll(Order order, Pageable pageable){
     return findAll(new Specification<Order>() {
         @Override
         public Predicate toPredicate(Root<Order> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
             List<Predicate> predicate = new ArrayList<>();
             if(!StringUtils.isEmpty(order.getOrderCode())){
                 predicate.add(criteriaBuilder.equal(root.get("orderCode").as(String.class), order.getOrderCode()));
             }
             if(!StringUtils.isEmpty(order.getProductName())){
                 predicate.add(criteriaBuilder.like(root.get("productName").as(String.class),"%"+order.getProductName()+"%"));
             }
             if(!StringUtils.isEmpty(order.getBrandName())){
                 predicate.add(criteriaBuilder.like(root.get("brandName").as(String.class),"%"+order.getBrandName()+"%"));
             }
             if(!StringUtils.isEmpty(order.getUsername())){
                 predicate.add(criteriaBuilder.like(root.get("username").as(String.class),"%"+order.getUsername()+"%"));
             }
             if(!StringUtils.isEmpty(order.getUserId())){
                 predicate.add(criteriaBuilder.equal(root.get("userId").as(String.class),order.getUserId()));
             }
             if(!StringUtils.isEmpty(order.getOrderStatus())){
                 predicate.add(criteriaBuilder.equal(root.get("orderStatus").as(String.class),order.getOrderStatus()));
             }
             if(!StringUtils.isEmpty(order.getCreator())){
                 predicate.add(criteriaBuilder.equal(root.get("creator").as(String.class),order.getCreator()));
             }
             if(!StringUtils.isEmpty(order.getBusinessGroup())){
                 predicate.add(criteriaBuilder.equal(root.get("businessGroup").as(String.class),order.getBusinessGroup()));
             }
             if(!StringUtils.isEmpty(order.getBusinessGroupMember())){
                 predicate.add(criteriaBuilder.equal(root.get("businessGroupMember").as(String.class),order.getBusinessGroupMember()));
             }
             Predicate[] pre = new Predicate[predicate.size()];

             return criteriaQuery.where(predicate.toArray(pre)).getRestriction();
         }
     },pageable);


    }
    default Page<Order> findAllByOrderQuery(OrderQuery orderQuery, Pageable pageable){
        return findAll(new Specification<Order>() {
            @Override
            public Predicate toPredicate(Root<Order> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicate = new ArrayList<>();
                if(!StringUtils.isEmpty(orderQuery.getOrderCode())){
                    predicate.add(criteriaBuilder.equal(root.get("orderCode").as(String.class), orderQuery.getOrderCode()));
                }
                if(!CollectionUtils.isEmpty(orderQuery.getProductCodes())){
                    Path<Object> productCodesPath = root.get("productCode");
                    CriteriaBuilder.In<Object> in = criteriaBuilder.in(productCodesPath);
                    List<String> productCodes = orderQuery.getProductCodes();
                    for(int i=0;i<productCodes.size();i++){
                        in.value(productCodes.get(i));
                    }
                    predicate.add(criteriaBuilder.and(criteriaBuilder.and(in)));
                }
                if(!StringUtils.isEmpty(orderQuery.getBrandCode())){
                    predicate.add(criteriaBuilder.equal(root.get("brandCode").as(String.class),orderQuery.getBrandCode()));
                }
                if(!StringUtils.isEmpty(orderQuery.getUsername())){
                    predicate.add(criteriaBuilder.like(root.get("username").as(String.class),"%"+orderQuery.getUsername()+"%"));
                }
                if(!StringUtils.isEmpty(orderQuery.getUserId())){
                    predicate.add(criteriaBuilder.equal(root.get("userId").as(String.class),orderQuery.getUserId()));
                }
                if(!StringUtils.isEmpty(orderQuery.getBrandName())){
                    predicate.add(criteriaBuilder.equal(root.get("brandName").as(String.class),orderQuery.getBrandName()));
                }
                if(!StringUtils.isEmpty(orderQuery.getProductName())){
                    predicate.add(criteriaBuilder.equal(root.get("productName").as(String.class),orderQuery.getProductName()));
                }
                if(!StringUtils.isEmpty(orderQuery.getOrderStatus())){
                    predicate.add(criteriaBuilder.equal(root.get("orderStatus").as(String.class),orderQuery.getOrderStatus()));
                }
                Predicate[] pre = new Predicate[predicate.size()];

                return criteriaQuery.where(predicate.toArray(pre)).getRestriction();
            }
        },pageable);


    }

    default Page<Order> findAllByOrderQueryByProductor(OrderQuery orderQuery, Pageable pageable){
        return findAll(new Specification<Order>() {
            @Override
            public Predicate toPredicate(Root<Order> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicate = new ArrayList<>();
                if(!StringUtils.isEmpty(orderQuery.getOrderCode())){
                    predicate.add(criteriaBuilder.equal(root.get("orderCode").as(String.class), orderQuery.getOrderCode()));
                }
                if(!CollectionUtils.isEmpty(orderQuery.getProductCodes())){
                    Path<Object> productCodesPath = root.get("productCode");
                    CriteriaBuilder.In<Object> in = criteriaBuilder.in(productCodesPath);
                    List<String> productCodes = orderQuery.getProductCodes();
                    for(int i=0;i<productCodes.size();i++){
                        in.value(productCodes.get(i));
                    }
                    predicate.add(criteriaBuilder.and(criteriaBuilder.and(in)));
                }
                if(!StringUtils.isEmpty(orderQuery.getBrandCode())){
                    Path<Object> brandPath = root.get("brandCode");
                    CriteriaBuilder.In<Object> in = criteriaBuilder.in(brandPath);
                    List<String> brandCodes = orderQuery.getBrandCodes();
                    for(int i=0;i<brandCodes.size();i++){
                        in.value(brandCodes.get(i));
                    }
                    predicate.add(criteriaBuilder.and(criteriaBuilder.and(in)));

                    //predicate.add(criteriaBuilder.equal(root.get("brand").as(String.class),orderQuery.getBrandCode()));
                }
                if(!StringUtils.isEmpty(orderQuery.getUsername())){
                    predicate.add(criteriaBuilder.like(root.get("username").as(String.class),"%"+orderQuery.getUsername()+"%"));
                }
                if(!StringUtils.isEmpty(orderQuery.getUserId())){
                    predicate.add(criteriaBuilder.equal(root.get("userId").as(String.class),orderQuery.getUserId()));
                }
                if(!StringUtils.isEmpty(orderQuery.getBrandName())){
                    predicate.add(criteriaBuilder.equal(root.get("brandName").as(String.class),orderQuery.getBrandName()));
                }
                if(!StringUtils.isEmpty(orderQuery.getPartnerCode())){
                    predicate.add(criteriaBuilder.equal(root.get("partnerCode").as(String.class),orderQuery.getPartnerCode()));
                }
                if(!StringUtils.isEmpty(orderQuery.getProductName())){
                    predicate.add(criteriaBuilder.equal(root.get("productName").as(String.class),orderQuery.getProductName()));
                }
                if(!StringUtils.isEmpty(orderQuery.getOrderStatus())){
                    predicate.add(criteriaBuilder.equal(root.get("orderStatus").as(String.class),orderQuery.getOrderStatus()));
                }
                if(!StringUtils.isEmpty(orderQuery.getOrderAuditStatus())){
                    predicate.add(criteriaBuilder.gt(root.get("auditStatus").as(Integer.class),orderQuery.getOrderAuditStatus()-1));
                }
                Predicate[] pre = new Predicate[predicate.size()];

                return criteriaQuery.where(predicate.toArray(pre)).getRestriction();
            }
        },pageable);


    }


    default Page<Order> queryOrderByUser(OrderQuery orderQuery, Pageable pageable){
        return findAll(new Specification<Order>() {
            @Override
            public Predicate toPredicate(Root<Order> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicate = new ArrayList<>();
                if(!StringUtils.isEmpty(orderQuery.getOrderCode())){
                    predicate.add(criteriaBuilder.equal(root.get("orderCode").as(String.class), orderQuery.getOrderCode()));
                }
                if(!CollectionUtils.isEmpty(orderQuery.getProductCodes())){
                    Path<Object> productCodesPath = root.get("productCode");
                    CriteriaBuilder.In<Object> in = criteriaBuilder.in(productCodesPath);
                    List<String> productCodes = orderQuery.getProductCodes();
                    for(int i=0;i<productCodes.size();i++){
                        in.value(productCodes.get(i));
                    }
                    predicate.add(criteriaBuilder.and(criteriaBuilder.and(in)));
                }
                if(!StringUtils.isEmpty(orderQuery.getBrandCode())){
                    Path<Object> brandPath = root.get("brandCode");
                    CriteriaBuilder.In<Object> in = criteriaBuilder.in(brandPath);
                    List<String> brandCodes = orderQuery.getBrandCodes();
                    for(int i=0;i<brandCodes.size();i++){
                        in.value(brandCodes.get(i));
                    }
                    predicate.add(criteriaBuilder.and(criteriaBuilder.and(in)));

                    //predicate.add(criteriaBuilder.equal(root.get("brand").as(String.class),orderQuery.getBrandCode()));
                }
                if(!StringUtils.isEmpty(orderQuery.getUsername())){
                    predicate.add(criteriaBuilder.like(root.get("username").as(String.class),"%"+orderQuery.getUsername()+"%"));
                }
                if(!StringUtils.isEmpty(orderQuery.getUserId())){
                    predicate.add(criteriaBuilder.equal(root.get("userId").as(String.class),orderQuery.getUserId()));
                }
                if(!StringUtils.isEmpty(orderQuery.getBrandName())){
                    predicate.add(criteriaBuilder.equal(root.get("brandName").as(String.class),orderQuery.getBrandName()));
                }
                if(!StringUtils.isEmpty(orderQuery.getPartnerCode())){
                    predicate.add(criteriaBuilder.equal(root.get("partnerCode").as(String.class),orderQuery.getPartnerCode()));
                }
                if(!StringUtils.isEmpty(orderQuery.getProductName())){
                    predicate.add(criteriaBuilder.equal(root.get("productName").as(String.class),orderQuery.getProductName()));
                }
                if(!StringUtils.isEmpty(orderQuery.getOrderStatus())){
                    predicate.add(criteriaBuilder.equal(root.get("orderStatus").as(String.class),orderQuery.getOrderStatus()));
                }
                if(!StringUtils.isEmpty(orderQuery.getOrderAuditStatus())){
                    predicate.add(criteriaBuilder.gt(root.get("auditStatus").as(Integer.class),orderQuery.getOrderAuditStatus()-1));
                }
                Predicate[] pre = new Predicate[predicate.size()];

                return criteriaQuery.where(predicate.toArray(pre)).getRestriction();
            }
        },pageable);


    }
    @Modifying
    @Query("update Order o set o.orderStatus=:orderStatus  where o.orderCode= :orderCode")
    void updateOrderStatus(@Param("orderCode") String orderCode, @Param("orderStatus")String orderStatus);

    @Modifying
    @Query("update Order o set o.auditStatus=:orderAuditStatus  where o.orderCode= :orderCode")
    void updateOrderAuditStatus(@Param("orderCode") String orderCode, @Param("orderAuditStatus")int orderAuditStatus);

    Order findByOrderCode(String orderCode);
    @Modifying
    @Query("update Order o set o.auditStatus=:orderAuditStatus,o.partnerCode=:partnerCode  where o.orderCode= :orderCode")
    void updatePartnerCode(String orderCode, int orderAuditStatus, String partnerCode);
}
